

Outpost 2 Tile Set file format
------------------------------

Note: This refers to the "well00??.bmp" files found in maps.vol.
Note: Tile sets must be in either 1 bpp, 8 bpp, or 16 bpp color modes. Other formats
cause the load to be aborted. (16 bpp causes a crash, probably 1 bpp too.)
Note: The tile set files can be replaced by standard bitmap files.
Note: The bitmap data should contain a column of all tiles.


Offset 	Size 	Description
------ 	---- 	-----------
0x0 	4 	"PBMP"
0x4 	4 	sectionSize (size of file - 16)
---------------------------
0x8 	4 	"head"
0xC 	4 	sectionSize (0x14 - 5 DWORD) Note: sectionSize bytes are read
		into an unchecked buffer of size 0x14 bytes (5 DWORDs).
		Any more data will overflow the buffer and corrupt the stack.
		(*Possible exploit*)
- - - - - - - - - - - - - -
0x10 	4 	numTagsLeft (2) - number of tags left (at this nesting level)
- - - - - - - - - - - - - -
0x14 	4 	pixelWidth (32 pixels wide)
0x18 	4 	pixelHeight (height of all tiles together)
0x1C 	4 	bitDepth
0x20 	4 	flags (always 8?) **TODO** figure this out
---------------------------
0x24 	4 	"PPAL"
0x28 	4 	sectionSize (1048 - size of subsections and sebsection data)
---------------------------
0x2C 	4 	"head"
0x30 	4 	sectionSize (4) Note: only 4 bytes of section will be read
- - - - - - - - - - - - - -
0x34 	4 	numTagsLeft (1) - number of tags left (at this nesting level)
---------------------------
0x38 	4 	"data"
0x3C 	4 	sectionSize (1024) - size of palette data
- - - - - - - - - - - - - -
0x40 	1024 	palette data - array of 4 byte palette entries (BGR order?)
---------------------------
0x440 	4 	"data"
0x444 	4 	sectionSize
- - - - - - - - - - - - - -
0x448 	1024*X 	tile data - pixel data for tiles (32x32 pixel tiles), 8 bits per 
		pixel, indexing into the palette stored earlier in the file




Loading Notes:
--------------

The above format is not absolutely required. The file is processed by loading tags
and then processing the following block of data according to the tag type. There
are two levels of nesting in the file structure. Reading a "PPAL" enters the next
nesting level. Each time a section tag is read, a count of remainings tags to read
is decremented. When the count reaches 0, processing returns to the previous level.
If the count on the outer level reaches 0, the load routine returns indicating a
successful load. Any read errors cause an immediate abort (such as EOF).

Note:
The count is initialized to -2 in Outpost2.exe. A count value of -1 is reserved
for error checking and could cause an abort (seems like useless error checking
that could never execute). To ensure the first few tags are read, a "large enough"
initial value is needed, and so -2 is the farthest value (when decrementing) from
0 that is allowed.

The first level scans for the following tags:
	"PBMP"  - ignored
	"PPAL"  - enters second level, if ((functionParam2 & 1) != 0)
		  **TODO** find out what happends for alternate parameter
		  Note: Seems functionParam2 is hardcoded to 1 tile set loads
	"head"  - reads sectionSize bytes into array (only space for 0x14 bytes)
	"data"  - allocates bitmap space and reads in bitmap data
	"BM"*
(* - The last 2 bytes of the "BM" tag are not considered (wild cards). A check
 for this tag is only performed under certain conditions. Namely, the number
 of tags left to read at this nesting level is >= 0.)

During the second level (after reading a "PPAL" tag) scans for the following tags:
	"PPAL"	- ignored
	"RIFF"
	"head"  - reads numTagsLeft (only 4 bytes are read, ignores sectionSize)
	"data"  - allocates palette space and reads in palette data
	"pspl"
	"ptpl"



Illustration of numTagsLeft
---------------------------
"PBMP"
"head"	(2 sections left at this level)
"PPAL"
	"head" (1 section left at this level)
	"data"
"data"


Logical structure of file
-------------------------
There is a logical distinction between tags consisting of all upper case letters
and tags consisting of all lower case letters. Upper case letters denote the start
of a major section of the file and all subsequent lower case tags belong to that
section (keeping nesting levels in mind). The first lower case tag in a major
section is the "head" tag. The fields following this tag are associated with the
major section. The numTagsLeft is expected to follow a "head" tag, but other fields
are dependent on the major section type. Data for a major section follows
subsection data.


Note: The logical structure of the file doesn't really matter to the loading code.
Note: If a section appears twice (and the numTagsLeft count is adjusted to
      compensate), then the previously read values are overwritten.
Note: Multiple data sections will cause memory leaks. There is no check when a
      data section is encountered as to whether or not memory has already been
      allocated. New memory is allocated, the data is read into the allocated
      memory, and the pointer to the returned memory is stored, overwriting any
      previously stored memory pointer.
Note: The first level scan does not run a size check on the "head" sectionSize
      when reading the "head" fields. It is assumed there will not be more than
      0x14 bytes of data to be read. (**Routine is Exploitable**)
